home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1998 July / EnigmA AMIGA RUN 29 (1998)(G.R. Edizioni)(IT)[!][issue 1998-07 & 08].iso / earcd / phase5 / lha-ppc / src / lhadd.c < prev    next >
C/C++ Source or Header  |  1997-12-04  |  14KB  |  610 lines

  1. /*----------------------------------------------------------------------*/
  2. /*            LHarc Add Command                */
  3. /*        This is part of LHarc UNIX Archiver Driver        */
  4. /*                                    */
  5. /*        Copyright(C) MCMLXXXIX  Yooichi.Tagawa            */
  6. /*                                    */
  7. /*  V0.00  Original                1988.05.23  Y.Tagawa    */
  8. /*  V1.00  Fixed                1989.09.22  Y.Tagawa    */
  9. /*  V1.02  Bug fix                1990.01.19  Y.Tagawa    */
  10. /*  V0.03  LHa for UNIX                1991.12.05  M.Oki    */
  11. /*----------------------------------------------------------------------*/
  12.  
  13. #include "lharc.h"
  14.  
  15. extern int encode_lzhuf ();
  16. extern int encode_stored_crc ();
  17.  
  18. static char new_archive_name_buffer [ FILENAME_LENGTH ];
  19. static char *new_archive_name;
  20. FILE *temporary_fp = NULL;
  21.  
  22. /*----------------------------------------------------------------------*/
  23. /*                                    */
  24. /*----------------------------------------------------------------------*/
  25.  
  26.  
  27.  
  28.  
  29. static void add_one(FILE *fp, FILE *nafp, LzHeader *hdr)
  30. {
  31.   long header_pos, next_pos, org_pos, data_pos;
  32.   long v_original_size, v_packed_size;
  33.  
  34.   reading_filename = hdr->name;
  35.   writting_filename = temporary_name;
  36.  
  37.   if (!fp && generic_format)    /* [generic] doesn't need directory info. */
  38.     return;
  39.   header_pos = ftell (nafp);
  40.   write_header (nafp, hdr);    /* DUMMY */
  41.  
  42.   if (hdr->original_size == 0)    /* empty file or directory */
  43.       return;            /* previous write_header is not DUMMY. (^_^) */
  44.  
  45.   org_pos = ftell (fp);
  46.   data_pos = ftell (nafp);
  47.  
  48.   hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
  49.                &v_original_size, &v_packed_size, hdr->name, hdr->method);
  50.  
  51.   if (v_packed_size < v_original_size)
  52.     {
  53.       next_pos = ftell (nafp);
  54.     }
  55.   else
  56.     {                /* retry by stored method */
  57.       fseek (fp, org_pos, SEEK_SET);
  58.       fseek (nafp, data_pos, SEEK_SET);
  59.       hdr->crc = encode_stored_crc (fp, nafp, hdr->original_size,
  60.                     &v_original_size, &v_packed_size);
  61.       fflush (nafp);
  62.       next_pos = ftell (nafp);
  63. #ifndef NOFTRUNCATE
  64.       ftruncate (fileno (nafp), next_pos);
  65. #endif
  66.       bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
  67.     }
  68.   hdr->original_size = v_original_size;
  69.   hdr->packed_size = v_packed_size;
  70.   fseek (nafp, header_pos, SEEK_SET);
  71.   write_header (nafp, hdr);
  72.   fseek (nafp, next_pos, SEEK_SET);
  73. }
  74.  
  75.  
  76. FILE *append_it(char *name, FILE *oafp, FILE *nafp)
  77. {
  78.   LzHeader ahdr, hdr;
  79.   FILE *fp;
  80.   long old_header;
  81.   int cmp;
  82.   int filec;
  83.   char **filev;
  84.   int i;
  85.   struct stat stbuf;
  86.   boolean directory;
  87.  
  88.   if (stat (name, &stbuf) < 0)
  89.     {
  90.       error ("cannot access", name); /* See cleaning_files, Why? */
  91.       return oafp;
  92.     }
  93.  
  94.   directory = is_directory (&stbuf);
  95.  
  96.   init_header (name, &stbuf, &hdr);
  97.  
  98.   if (!directory && !noexec)
  99.     fp = xfopen (name, READ_BINARY);
  100.   else
  101.     fp = NULL;
  102.  
  103.   while (oafp)
  104.     {
  105.       old_header = ftell (oafp);
  106.       if (!get_header (oafp, &ahdr))
  107.     {
  108.       fclose (oafp);
  109.       oafp = NULL;
  110.       break;
  111.     }
  112.       else
  113.     {
  114.       cmp = STRING_COMPARE (ahdr.name, hdr.name);
  115.       if (cmp < 0)
  116.         {            /* SKIP */
  117.           /* copy old to new */
  118.           if (!noexec)
  119.         {
  120.           fseek (oafp, old_header, SEEK_SET);
  121.           copy_old_one (oafp, nafp, &ahdr);
  122.         }
  123.           else
  124.         fseek (oafp, ahdr.packed_size, SEEK_CUR);
  125.         }
  126.       else if (cmp == 0)
  127.         {            /* REPLACE */
  128.           /* drop old archive's */
  129.           fseek (oafp, ahdr.packed_size, SEEK_CUR);
  130.           break;
  131.         }
  132.       else            /* cmp > 0, INSERT */
  133.         {
  134.           fseek (oafp, old_header, SEEK_SET);
  135.           break;
  136.         }
  137.     }
  138.     }
  139.  
  140.   if (update_if_newer)
  141.     {
  142.       if (!oafp ||        /* not in archive */
  143.       cmp > 0 ||        /* // */
  144.       ahdr.unix_last_modified_stamp < /* newer than archive's */
  145.       hdr.unix_last_modified_stamp)
  146.     {
  147.       if (noexec)
  148.         printf ("ADD %s\n", name);
  149.       else
  150.         add_one (fp, nafp, &hdr);
  151.     }
  152.       else /* cmp == 0 */
  153.     {            /* copy old to new */
  154.       if (!noexec)
  155.         {
  156.           fseek (oafp, old_header, SEEK_SET);
  157.           copy_old_one (oafp, nafp, &ahdr);
  158.         }
  159.     }
  160.     }
  161.   else
  162.     {
  163.       if (!oafp || cmp > 0)    /* not in archive or dropped */
  164.     {
  165.       if (noexec)
  166.         printf ("ADD %s\n", name);
  167.       else
  168.         add_one (fp, nafp, &hdr);
  169.     }
  170.       else /* cmp == 0 */    /* replace */
  171.     {
  172.       if (noexec)
  173.         printf ("REPLACE\n");
  174.       else
  175.         add_one (fp, nafp, &hdr);
  176.     }
  177.     }
  178.  
  179.   if (!directory)
  180.     {
  181.       if (!noexec)
  182.     fclose (fp);
  183.     }
  184.   else
  185.     {            /* recurcive call */
  186.       if (find_files (name, &filec, &filev))
  187.     {
  188.       for (i = 0; i < filec; i ++)
  189.         oafp = append_it (filev[i], oafp, nafp);
  190.       free_files (filec, filev);
  191.     }
  192.     }
  193.   return oafp;
  194. }
  195.  
  196. static void find_update_files(FILE *oafp)
  197. {
  198.   char name[FILENAME_LENGTH];
  199.   struct string_pool sp;
  200.   LzHeader hdr;
  201.   long pos;
  202.   struct stat stbuf;
  203.   int len;
  204.  
  205.   pos = ftell (oafp);
  206.  
  207.   init_sp (&sp);
  208.   while (get_header (oafp, &hdr))
  209.     {
  210.       if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
  211.     {
  212.       if (stat (hdr.name, &stbuf) >= 0) /* exist ? */
  213.         add_sp (&sp, hdr.name, strlen (hdr.name) + 1);
  214.     }
  215.       else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY)
  216.     {
  217.       strcpy (name, hdr.name);
  218.       len = strlen (name);
  219.       if (len > 0 && name[len - 1] == '/')
  220.         name[--len] = '\0'; /* strip tail '/' */
  221.       if (stat (name, &stbuf) >= 0) /* exist ? */
  222.         add_sp (&sp, name, len+1);
  223.     }
  224.       fseek (oafp, hdr.packed_size, SEEK_CUR);
  225.     }
  226.  
  227.   fseek (oafp, pos, SEEK_SET);
  228.  
  229.   finish_sp (&sp, &cmd_filec, &cmd_filev);
  230. }
  231.  
  232. static void delete(FILE *oafp, FILE *nafp)
  233. {
  234.   LzHeader ahdr;
  235.   long old_header_pos;
  236.  
  237.   old_header_pos = ftell (oafp);
  238.   while (get_header (oafp, &ahdr))
  239.     {
  240.       if (need_file (ahdr.name))
  241.     {            /* skip */
  242.       fseek (oafp, ahdr.packed_size, SEEK_CUR);
  243.       if (noexec)
  244.         printf ("DELETE %s\n", ahdr.name);
  245.       else if (verbose)
  246.         printf ("Delete %s\n", ahdr.name);
  247.     }
  248.       else
  249.     {            /* copy */
  250.       if (noexec)
  251.         {
  252.           fseek (oafp, ahdr.packed_size, SEEK_CUR);
  253.         }
  254.       else
  255.         {
  256.           fseek (oafp, old_header_pos, SEEK_SET);
  257.           copy_old_one (oafp, nafp, &ahdr);
  258.         }
  259.     }
  260.       old_header_pos = ftell (oafp);
  261.     }
  262.   return;
  263. }
  264.  
  265. /*----------------------------------------------------------------------*/
  266. /*                                    */
  267. /*----------------------------------------------------------------------*/
  268. static FILE *build_temporary_file(void)
  269. {
  270. #ifndef AMIGA
  271.   int old_umask;
  272. #endif
  273.   FILE *afp;
  274.  
  275.   build_temporary_name ();
  276.   signal (SIGINT, interrupt);
  277. #ifndef AMIGA
  278.   signal (SIGHUP, interrupt);
  279.  
  280.   old_umask = umask (077);
  281. #endif
  282.   afp = xfopen (temporary_name, WRITE_BINARY);
  283.   remove_temporary_at_error = TRUE;
  284.   temporary_fp = afp;
  285. #ifndef AMIGA
  286.   umask (old_umask);
  287. #endif
  288.  
  289.   return afp;
  290. }
  291.  
  292. static void build_backup_file(void)
  293. {
  294.   
  295.   build_backup_name (backup_archive_name, archive_name);
  296.   if (!noexec)
  297.     {
  298.       signal (SIGINT, SIG_IGN);
  299. #ifndef AMIGA
  300.       signal (SIGHUP, SIG_IGN);
  301. #endif
  302.       if (rename (archive_name, backup_archive_name) < 0)
  303.         fatal_error (archive_name);
  304.       recover_archive_when_interrupt = TRUE;
  305.       signal (SIGINT, interrupt);
  306. #ifndef AMIGA
  307.       signal (SIGHUP, interrupt);
  308. #endif
  309.     }
  310. }
  311.  
  312. static void report_archive_name_if_different(void)
  313. {
  314.   if (!quiet && new_archive_name == new_archive_name_buffer)
  315.     {
  316.       /* warning at old archive is SFX */
  317.       printf ("New archive file is \"%s\"\n", new_archive_name);
  318.     }
  319. }
  320.  
  321. #ifdef TMP_FILENAME_TEMPLATE
  322. void temporary_to_new_archive_file(long new_archive_size)
  323. {
  324.   FILE *oafp, *nafp;
  325.  
  326.   oafp = xfopen (temporary_name, READ_BINARY);
  327.   if (!strcmp(new_archive_name, "-"))
  328.     {
  329.       nafp = stdout;
  330.       writting_filename = "starndard output";
  331.     }
  332.   else
  333.     {
  334.       nafp = xfopen (new_archive_name, WRITE_BINARY);
  335.       writting_filename = archive_name;
  336.     }
  337.   reading_filename = temporary_name;
  338.   copyfile (oafp, nafp, new_archive_size, 0);
  339.   if (nafp != stdout) fclose (nafp);
  340.   fclose (oafp);
  341.  
  342.   recover_archive_when_interrupt = FALSE;
  343.   unlink (temporary_name);
  344.  
  345.   remove_temporary_at_error = FALSE;
  346. }
  347. #else
  348. temporary_to_new_archive_file (new_archive_size)
  349. long new_archive_size;
  350. {
  351.   char *p;
  352.   p = (char *)rindex(new_archive_name,'/');
  353.   p = p ? p+1 : new_archive_name;
  354.   unlink ( new_archive_name );
  355.   if ( rename ( temporary_name , p )<0 ) {
  356.     fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
  357.     exit(1);
  358.   }
  359. }
  360. #endif
  361.  
  362. static void set_archive_file_mode(void)
  363. {
  364. #ifndef AMIGA
  365.   int umask_value;
  366.   struct stat stbuf;
  367.  
  368.   if (archive_file_gid < 0)
  369.     {
  370.       umask (umask_value = umask (0));
  371.       archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
  372.       if (stat (".", &stbuf) >= 0)
  373.     archive_file_gid = stbuf.st_gid;
  374.     }
  375.   if (archive_file_gid >= 0)
  376.     chown (new_archive_name, getuid (), archive_file_gid);
  377.  
  378.   chmod (new_archive_name, archive_file_mode);
  379. #endif
  380. }
  381.  
  382. /*----------------------------------------------------------------------*/
  383. /*        REMOVE FILE/DIRECTORY                    */
  384. /*----------------------------------------------------------------------*/
  385.  
  386. static void remove_files(int filec, char **filev);
  387.  
  388. static void remove_one(char *name)
  389. {
  390.   struct stat stbuf;
  391.   int filec;
  392.   char **filev;
  393.  
  394.   if (stat (name, &stbuf) < 0)
  395.     {
  396.       warning ("Cannot access", name);
  397.     }
  398.   else if (is_directory (&stbuf))
  399.     {
  400.       if (find_files (name, &filec, &filev))
  401.     {
  402.       remove_files (filec, filev);
  403.       free_files (filec, filev);
  404.     }
  405.       else
  406.     warning ("Cannot open directory", name);
  407.  
  408.       if (noexec)
  409.     printf ("REMOVE DIRECTORY %s\n", name);
  410.       else if (rmdir (name) < 0)
  411.     warning ("Cannot remove directory", name);
  412.       else if (verbose)
  413.     printf ("Removed %s.\n", name);
  414.     }
  415.   else if (is_regularfile (&stbuf))
  416.     {
  417.       if (noexec)
  418.     printf ("REMOVE FILE %s.\n", name);
  419.       else if (unlink (name) < 0)
  420.     warning ("Cannot remove", name);
  421.       else if (verbose)
  422.     printf ("Removed %s.\n", name);
  423.     }
  424.   else
  425.     {
  426.       error ("Cannot remove (not a file or directory)", name);
  427.     }
  428. }
  429.  
  430. static void remove_files(int filec, char **filev)
  431. {
  432.   int i;
  433.  
  434.   for (i = 0; i < filec; i++)
  435.     remove_one (filev[i]);
  436. }
  437.  
  438. /*----------------------------------------------------------------------*/
  439. /*                                    */
  440. /*----------------------------------------------------------------------*/
  441.  
  442. void cmd_add(void)
  443. {
  444.   LzHeader ahdr;
  445.   FILE *oafp, *nafp;
  446.   int i;
  447.   long old_header;
  448.   boolean old_archive_exist;
  449.   long new_archive_size;
  450.  
  451.   /* exit if no operation */
  452.   if (!update_if_newer && cmd_filec == 0)
  453.     {
  454.       error ("No files given in argument, do nothing.", "");
  455.       return;
  456.     }
  457.  
  458.   /* open old archive if exist */
  459.   if ((oafp = open_old_archive ()) == NULL)
  460.     old_archive_exist = FALSE;
  461.   else
  462.     old_archive_exist = TRUE;
  463.  
  464.   if (update_if_newer && cmd_filec == 0 && !oafp)
  465.     fatal_error (archive_name); /* exit if cannot execute automatic update */
  466.   errno = 0;
  467.  
  468.   if (new_archive && old_archive_exist)
  469.     {
  470.       fclose (oafp);
  471.       oafp = NULL;
  472.     }
  473.  
  474.   if (oafp && archive_is_msdos_sfx1 (archive_name))
  475.     {
  476.       skip_msdos_sfx1_code (oafp);
  477.       build_standard_archive_name (new_archive_name_buffer, archive_name);
  478.       new_archive_name = new_archive_name_buffer;
  479.     }
  480.   else
  481.     {
  482.       new_archive_name = archive_name;
  483.     }
  484.  
  485.   /* build temporary file */
  486.   if (!noexec)
  487.     nafp = build_temporary_file ();
  488.  
  489.   /* find needed files when automatic update */
  490.   if (update_if_newer && cmd_filec == 0)
  491.     find_update_files (oafp);
  492.  
  493.   /* build new archive file */
  494.   /* cleaning arguments */
  495.   cleaning_files (&cmd_filec, &cmd_filev);
  496.   if (cmd_filec == 0)
  497.     {
  498.       if (oafp)
  499.     fclose (oafp);
  500.       if  (!noexec)
  501.     fclose (nafp);
  502.       return;
  503.     }
  504.  
  505.   for (i = 0; i < cmd_filec; i ++)
  506.     oafp = append_it (cmd_filev[i], oafp, nafp);
  507.   if (oafp)
  508.     {
  509.       old_header = ftell (oafp);
  510.       while (get_header (oafp, &ahdr))
  511.     {
  512.       if (noexec)
  513.         fseek (oafp, ahdr.packed_size, SEEK_CUR);
  514.       else
  515.         {
  516.           fseek (oafp, old_header, SEEK_SET);
  517.           copy_old_one (oafp, nafp, &ahdr);
  518.         }
  519.       old_header = ftell (oafp);
  520.     }
  521.       fclose (oafp);
  522.     }
  523.   if (!noexec)
  524.     {
  525.       write_archive_tail (nafp);
  526.       new_archive_size = ftell (nafp);
  527.       fclose (nafp);
  528.     }
  529.  
  530.   /* build backup archive file */
  531.   if (old_archive_exist)
  532.     build_backup_file ();
  533.  
  534.   report_archive_name_if_different ();
  535.  
  536.   /* copy temporary file to new archive file */
  537.   if (!noexec && (!strcmp(new_archive_name, "-") ||
  538.           rename (temporary_name, new_archive_name) < 0))
  539.     temporary_to_new_archive_file (new_archive_size);
  540.  
  541.   /* set new archive file mode/group */
  542.   set_archive_file_mode ();
  543.  
  544.   /* remove archived files */
  545.   if (delete_after_append)
  546.     remove_files (cmd_filec, cmd_filev);
  547.  
  548.   return;
  549. }
  550.  
  551.  
  552. void cmd_delete(void)
  553. {
  554.   FILE *oafp, *nafp;
  555.   long new_archive_size;
  556.  
  557.   /* open old archive if exist */
  558.   if ((oafp = open_old_archive ()) == NULL)
  559.     fatal_error (archive_name);
  560.   errno = 0;
  561.  
  562.   /* exit if no operation */
  563.   if (cmd_filec == 0)
  564.     {
  565.       fclose (oafp);
  566.       warning ("No files given in argument, do nothing.", "");
  567.       return;
  568.     }
  569.  
  570.   if (archive_is_msdos_sfx1 (archive_name))
  571.     {
  572.       skip_msdos_sfx1_code (oafp);
  573.       build_standard_archive_name (new_archive_name_buffer, archive_name);
  574.       new_archive_name = new_archive_name_buffer;
  575.     }
  576.   else
  577.     {
  578.       new_archive_name = archive_name;
  579.     }
  580.  
  581.   /* build temporary file */
  582.   if (!noexec)
  583.     nafp = build_temporary_file ();
  584.  
  585.   /* build new archive file */
  586.   delete (oafp, nafp);
  587.   fclose (oafp);
  588.  
  589.   if (!noexec)
  590.     {
  591.       write_archive_tail (nafp);
  592.       new_archive_size = ftell (nafp);
  593.       fclose (nafp);
  594.     }
  595.  
  596.   /* build backup archive file */
  597.   build_backup_file ();
  598.  
  599.   report_archive_name_if_different ();
  600.  
  601.   /* copy temporary file to new archive file */
  602.   if (!noexec && rename (temporary_name, new_archive_name) < 0)
  603.     temporary_to_new_archive_file (new_archive_size);
  604.  
  605.   /* set new archive file mode/group */
  606.   set_archive_file_mode ();
  607.  
  608.   return;
  609. }
  610.